package com.yupi.springbootinit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.controller.WorkflowTaskController;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.mapper.WorkflowTaskMapper;
import com.yupi.springbootinit.model.entity.Department;
import com.yupi.springbootinit.model.entity.User;
import com.yupi.springbootinit.model.entity.WorkflowTask;
import com.yupi.springbootinit.model.vo.DepartmentTaskStatsVO;
import com.yupi.springbootinit.model.vo.WorkflowTaskVO;
import com.yupi.springbootinit.model.vo.PersonalTaskStatsVO;
import com.yupi.springbootinit.service.WorkflowTaskService;
import com.yupi.springbootinit.service.workflow.*;
import com.yupi.springbootinit.service.ProductionOperationRecordService;
import com.yupi.springbootinit.service.TaskOperationLogService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 工作流任务服务实现类（重构版）
 * 
 * 职责：
 * 1. 作为主服务协调器，委托具体业务给专门的子服务
 * 2. 实现WorkflowTaskService接口
 * 3. 处理事务管理
 * 
 * 重构说明：
 * - 原850行代码拆分为6个专门的服务类
 * - 每个服务类职责单一，易于维护和测试
 * - 主服务类只负责协调和事务管理
 */
@Slf4j
@Service
public class WorkflowTaskServiceImpl extends ServiceImpl<WorkflowTaskMapper, WorkflowTask> implements WorkflowTaskService {

    @Resource
    private WorkflowTaskCreationService taskCreationService;
    
    @Resource
    private WorkflowTaskQueryService taskQueryService;
    
    @Resource
    private WorkflowTaskStatisticsService taskStatisticsService;
    
    @Resource
    private WorkflowTaskOperationService taskOperationService;

    @Resource
    private WorkflowTaskPermissionService taskPermissionService;

    @Resource
    private ProductionOperationRecordService productionOperationRecordService;

    @Resource
    private TaskOperationLogService taskOperationLogService;

    @Resource
    private WorkflowTaskMapper workflowTaskMapper;

    @Resource
    private WorkflowTaskUtils workflowTaskUtils;

    // ==================== 任务创建相关 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createProcessSheetTaskForSalesOrder(Long salesOrderId, String orderNumber, String productName, Long creatorId, String creatorName) {
        taskCreationService.createProcessSheetTaskForSalesOrder(salesOrderId, orderNumber, productName, creatorId, creatorName);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createScheduleTaskForSalesOrder(Long salesOrderId, String orderNumber, String productName, Long creatorId, String creatorName) {
        taskCreationService.createScheduleTaskForSalesOrder(salesOrderId, orderNumber, productName, creatorId, creatorName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createPublishBatchTaskForBatch(Long batchId, String orderNumber, String batchCode,
                                               Long parentTaskId, Long creatorId, String creatorName) {
        if (batchId == null) {
            log.warn("创建批次发布待办失败: batchId 为空");
            return;
        }

        log.info("开始创建批次发布子任务: batchId={}, batchCode={}, parentTaskId={}", batchId, batchCode, parentTaskId);

        Long existingCount = workflowTaskMapper.selectCount(
                new LambdaQueryWrapper<WorkflowTask>()
                        .eq(WorkflowTask::getTaskType, "PUBLISH_BATCH")
                        .eq(WorkflowTask::getBizType, "PROCESS_BATCH")
                        .eq(WorkflowTask::getBizId, batchId)
                        .eq(WorkflowTask::getParentTaskId, parentTaskId)
                        .eq(WorkflowTask::getIsDelete, 0)
        );

        if (existingCount != null && existingCount > 0) {
            log.info("批次发布任务已存在，跳过创建: batchId={}, parentTaskId={}, count={}",
                    batchId, parentTaskId, existingCount);
            return;
        }

        Department dept = workflowTaskUtils.getDepartmentByCode("PMC001");
        if (dept == null) {
            log.error("创建批次发布待办失败：未找到PMC部门，deptCode=PMC001");
            return;
        }

        Long claimedBy = null;
        String claimedByName = null;
        LocalDateTime claimedTime = null;

        if (parentTaskId != null) {
            WorkflowTask parentTask = workflowTaskMapper.selectById(parentTaskId);
            if (parentTask != null && parentTask.getClaimedBy() != null) {
                claimedBy = parentTask.getClaimedBy();
                claimedByName = parentTask.getClaimedByName();
                claimedTime = LocalDateTime.now();
                log.info("子任务继承父任务认领人: parentTaskId={}, claimedBy={}, claimedByName={}",
                        parentTaskId, claimedBy, claimedByName);
            } else {
                log.info("父任务未被认领: parentTaskId={}", parentTaskId);
            }
        } else {
            log.warn("未指定父任务ID，子任务不继承认领人");
        }

        WorkflowTask task = new WorkflowTask();
        task.setTaskTitle("批次发布");
        task.setTaskDescription("发布批次 - " + StringUtils.defaultString(batchCode, ""));
        task.setTaskType("PUBLISH_BATCH");
        task.setBizType("PROCESS_BATCH");
        task.setBizId(batchId);
        task.setBizNumber(StringUtils.defaultString(orderNumber));
        task.setProductName(StringUtils.defaultString(batchCode));
        task.setDepartmentId(dept.getId());
        task.setDepartmentName(dept.getDepartmentName());
        task.setParentTaskId(parentTaskId);
        task.setPriority("NORMAL");
        task.setCreatedBy(creatorId);
        task.setCreatedByName(creatorName);

        if (claimedBy != null) {
            task.setTaskStatus("IN_PROGRESS");
            task.setClaimedBy(claimedBy);
            task.setClaimedByName(claimedByName);
            task.setClaimedTime(claimedTime);
        } else {
            task.setTaskStatus("PENDING");
        }

        LocalDateTime now = LocalDateTime.now();
        task.setCreateTime(now);
        task.setUpdateTime(now);
        task.setIsDelete(0);

        int rows = workflowTaskMapper.insert(task);
        if (rows > 0) {
            log.info("批次发布子任务创建成功: taskId={}, batchId={}, batchCode={}, parentTaskId={}, claimedBy={}, status={}",
                    task.getId(), batchId, batchCode, parentTaskId, claimedBy, task.getTaskStatus());
        } else {
            log.error("批次发布子任务创建失败: batchId={}, rows={}", batchId, rows);
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createProductionWorkorderTaskForBatch(Long batchId, String orderNumber, String productName, Long creatorId, String creatorName) {
        taskCreationService.createProductionWorkorderTaskForBatch(batchId, orderNumber, productName, creatorId, creatorName);
    }

    // ==================== 任务查询相关 ====================

    @Override
    public Page<WorkflowTask> pageDepartmentTasks(Long departmentId, String status, long current, long size) {
        return taskQueryService.pageDepartmentTasks(departmentId, status, current, size);
    }

    @Override
    public Page<WorkflowTaskVO> pageDepartmentTasksVO(Long departmentId, String status, long current, long size, User currentUser) {
        return taskQueryService.pageDepartmentTasksVO(departmentId, status, current, size, currentUser);
    }

    @Override
    public Page<WorkflowTaskVO> pageMyTasks(Long userId, String status, long current, long size, User currentUser) {
        return taskQueryService.pageMyTasks(userId, status, current, size, currentUser);
    }

    @Override
    public Page<WorkflowTaskVO> pageMyProcessSheetTasks(Long userId, String status, long current, long size, User currentUser) {
        return taskQueryService.pageMyProcessSheetTasks(userId, status, current, size, currentUser);
    }

    @Override
    public Page<WorkflowTaskVO> pageProcessSheetTasks(Long userId, boolean isAdmin, String status, long current, long size, User currentUser) {
        return taskQueryService.pageProcessSheetTasks(userId, isAdmin, status, current, size, currentUser);
    }

    // ==================== 任务统计相关 ====================

    @Override
    public DepartmentTaskStatsVO getDepartmentTaskStats(Long departmentId) {
        return taskStatisticsService.getDepartmentTaskStats(departmentId);
    }

    @Override
    public PersonalTaskStatsVO getPersonalTaskStats(Long userId) {
        return taskStatisticsService.getPersonalTaskStats(userId);
    }

    @Override
    public List<WorkflowTaskVO> listSubTasks(Long parentTaskId, User currentUser) {
        return taskQueryService.listSubTasks(parentTaskId, currentUser);
    }

    @Override
    public WorkflowTaskController.TaskStatistics getTaskStatistics(Long departmentId, Long userId) {
        // 部门统计
        DepartmentTaskStatsVO deptStats = taskStatisticsService.getDepartmentTaskStats(departmentId);
        // 个人统计
        PersonalTaskStatsVO personalStats = taskStatisticsService.getPersonalTaskStats(userId);

        com.yupi.springbootinit.controller.WorkflowTaskController.TaskStatistics stats =
                new com.yupi.springbootinit.controller.WorkflowTaskController.TaskStatistics();
        // 通过反射填充字段，规避 Lombok setter 在当前编译环境不可解析的问题
        try {
            setStatsField(stats, "departmentPendingCount", deptStats != null ? deptStats.getPending() : 0L);
            setStatsField(stats, "departmentInProgressCount", deptStats != null ? deptStats.getInProgress() : 0L);
            setStatsField(stats, "departmentDoneCount", deptStats != null ? deptStats.getCompleted() : 0L);

            setStatsField(stats, "myPendingCount", personalStats != null ? personalStats.getPending() : 0L);
            setStatsField(stats, "myInProgressCount", 0L); // 个人不再区分“进行中”口径
            setStatsField(stats, "myDoneCount", personalStats != null ? personalStats.getCompleted() : 0L);
            setStatsField(stats, "overdueCount", personalStats != null ? personalStats.getOverdue() : 0L);
        } catch (Exception e) {
            log.warn("填充任务统计字段失败，使用默认值", e);
        }
        return stats;
    }

    // 反射填充内部类字段（避免 Lombok setter 在编译环境不可见）
    private void setStatsField(Object obj, String fieldName, Object value) throws Exception {
        java.lang.reflect.Field f = obj.getClass().getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(obj, value);
    }

    // ==================== 任务操作相关 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean claimTask(Long taskId, Long userId, String userName, Long departmentId) {
        if (taskId == null || taskId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "任务ID不能为空");
        }

        log.info("开始认领任务: taskId={}, userId={}, userName={}", taskId, userId, userName);

        // ========== 1. 查询任务 ==========
        WorkflowTask task = workflowTaskMapper.selectById(taskId);
        if (task == null || task.getIsDelete() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "任务不存在");
        }

        // ========== 2. 权限检查 ==========
        if (!departmentId.equals(task.getDepartmentId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR,
                    "您不属于该任务的归属部门，无权认领");
        }

        // ========== 3. 状态检查 ==========
        if ("IN_PROGRESS".equals(task.getTaskStatus())) {
            if (userId.equals(task.getClaimedBy())) {
                log.info("任务已被当前用户认领，直接返回: taskId={}, userId={}", taskId, userId);
                return true;
            }
            throw new BusinessException(ErrorCode.OPERATION_ERROR,
                    "该任务已被其他人认领：" + task.getClaimedByName());
        }

        if ("DONE".equals(task.getTaskStatus())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR,
                    "该任务已完成，无法认领");
        }

        // ========== 4. ✅ 使用 UpdateWrapper 更新任务（驼峰式字段名）==========
        LocalDateTime now = LocalDateTime.now();

        UpdateWrapper<WorkflowTask> uw = new UpdateWrapper<>();
        uw.eq("id", taskId)
                .eq("isDelete", 0)                      // ✅ 驼峰式
                .eq("taskStatus", "PENDING")            // ✅ 驼峰式
                .set("taskStatus", "IN_PROGRESS")       // ✅ 驼峰式
                .set("claimedBy", userId)               // ✅ 驼峰式
                .set("claimedByName", userName)         // ✅ 驼峰式
                .set("claimedTime", now)                // ✅ 驼峰式
                .set("updateTime", now)                 // ✅ 驼峰式
                .setSql("version = version + 1");

        int rows = workflowTaskMapper.update(null, uw);

        if (rows == 0) {
            log.error("认领失败，可能任务状态已变更: taskId={}, currentStatus={}",
                    taskId, task.getTaskStatus());
            throw new BusinessException(ErrorCode.OPERATION_ERROR,
                    "认领失败，任务状态可能已被其他人修改，请刷新后重试");
        }

        log.info("✅ 任务认领成功: taskId={}, userId={}, userName={}", taskId, userId, userName);

        // ========== 5. ✅ 如果是父任务，同步认领所有子任务 ==========
        if ("CREATE_SCHEDULE".equals(task.getTaskType())) {
            UpdateWrapper<WorkflowTask> subTaskUw = new UpdateWrapper<>();
            subTaskUw.eq("parentTaskId", taskId)          // ✅ 驼峰式
                    .eq("taskStatus", "PENDING")          // ✅ 驼峰式
                    .eq("isDelete", 0)                    // ✅ 驼峰式
                    .set("taskStatus", "IN_PROGRESS")     // ✅ 驼峰式
                    .set("claimedBy", userId)             // ✅ 驼峰式
                    .set("claimedByName", userName)       // ✅ 驼峰式
                    .set("claimedTime", now)              // ✅ 驼峰式
                    .set("updateTime", now)               // ✅ 驼峰式
                    .setSql("version = version + 1");

            int subTaskRows = workflowTaskMapper.update(null, subTaskUw);

            log.info("✅ 父任务认领成功，同步认领子任务: parentTaskId={}, userId={}, 子任务数量={}",
                    taskId, userId, subTaskRows);
        }

        return true;
    }

    // 新增：开始任务（记录审计）
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean startTask(Long taskId, Long operatorId, String operatorName, Long recorderUserId, String recorderUserName, String remark) {
        WorkflowTask task = this.getById(taskId);
        if (task == null || (task.getIsDelete() != null && task.getIsDelete() == 1)) {
            return false;
        }
        // 状态校验：仅 PENDING 或 IN_PROGRESS 可开始（若未认领则自动认领为当前用户）
        if ("PENDING".equals(task.getTaskStatus())) {
            task.setTaskStatus("IN_PROGRESS");
            task.setClaimedBy(recorderUserId);
            task.setClaimedByName(recorderUserName);
            task.setClaimedTime(java.time.LocalDateTime.now());
            // 记录任务操作日志：START前的认领动作可视为已认领
            taskOperationLogService.log(taskId, "CLAIM", recorderUserName, "自动认领（开始任务）", java.time.LocalDateTime.now());
        }
        // 任务操作日志（START）
        taskOperationLogService.log(taskId, "START", operatorName != null ? operatorName : recorderUserName, remark, java.time.LocalDateTime.now());
        // 审计记录
        productionOperationRecordService.recordStart(taskId,
                "PROCESS_BATCH".equals(task.getBizType()) ? task.getBizId() : null,
                null, null,
                "PRODUCTION_PREP_CLEANING".equals(task.getTaskType()) ? "PREP_CLEANING" : "PROCESS_EXECUTION",
                operatorId, operatorName, recorderUserId, recorderUserName, remark);
        task.setUpdateTime(java.time.LocalDateTime.now());
        // 使用 UpdateWrapper 避免乐观锁参数缺失
        java.time.LocalDateTime now2 = task.getUpdateTime() != null ? task.getUpdateTime() : java.time.LocalDateTime.now();
        com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<com.yupi.springbootinit.model.entity.WorkflowTask> uwStart =
                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<>();
        uwStart.eq("id", taskId)
               .eq("isDelete", 0)
               .set("updateTime", now2)
               .setSql("version = version + 1");
        if ("PENDING".equals(task.getTaskStatus())) {
            uwStart.set("taskStatus", "IN_PROGRESS")
                   .set("claimedBy", recorderUserId)
                   .set("claimedByName", recorderUserName)
                   .set("claimedTime", now2);
        }
        this.baseMapper.update(null, uwStart);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeTask(Long taskId, Long userId, String userName, String remark) {
        return taskOperationService.completeTask(taskId, userId, userName, remark);
    }

    // 清机/工单重载：在 WorkflowTaskController 已调用新的 complete 重载，这里保持旧方法兼容
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeTask(Long taskId, Long operatorId, String operatorName, Long recorderUserId, String recorderUserName, String remark) {
        WorkflowTask task = this.getById(taskId);
        if (task == null || (task.getIsDelete() != null && task.getIsDelete() == 1)) {
            return false;
        }
        // 任务操作日志（COMPLETE）
        taskOperationLogService.log(taskId, "COMPLETE", operatorName != null ? operatorName : recorderUserName, remark, java.time.LocalDateTime.now());
        // 写审计
        productionOperationRecordService.recordComplete(taskId,
                "PROCESS_BATCH".equals(task.getBizType()) ? task.getBizId() : null,
                null, null,
                "PRODUCTION_PREP_CLEANING".equals(task.getTaskType()) ? "PREP_CLEANING" : "PROCESS_EXECUTION",
                operatorId, operatorName, recorderUserId, recorderUserName, remark);

        // 完成当前任务
        task.setTaskStatus("DONE");
        task.setCompletedTime(java.time.LocalDateTime.now());
        task.setCompletionRemark(remark);
        // 使用 UpdateWrapper 避免乐观锁参数缺失
        java.time.LocalDateTime doneNow = java.time.LocalDateTime.now();
        com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<com.yupi.springbootinit.model.entity.WorkflowTask> uwDone =
                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<>();
        uwDone.eq("id", taskId)
              .eq("isDelete", 0)
              .set("taskStatus", "DONE")
              .set("completedTime", doneNow)
              .set("completionRemark", remark)
              .set("updateTime", doneNow)
              .setSql("version = version + 1");
        this.baseMapper.update(null, uwDone);

        // 清机完成后，创建生产工单任务
        if ("PRODUCTION_PREP_CLEANING".equals(task.getTaskType()) && "PROCESS_BATCH".equals(task.getBizType())) {
            try {
                // 获取版次信息以便填充名称（此处仅用产品名字段，若为空可后续优化）
                taskCreationService.createProductionWorkorderTaskForBatch(task.getBizId(), task.getBizNumber(), task.getProductName(),
                        recorderUserId, recorderUserName);
            } catch (Exception e) {
                log.warn("清机完成后创建生产工单任务失败，batchId={}", task.getBizId(), e);
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeProcessSheetTaskForSalesOrder(Long salesOrderId, Long completedBy, String completedByName) {
        return taskOperationService.completeProcessSheetTaskForSalesOrder(salesOrderId, completedBy, completedByName);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completePublishBatchTaskForBatch(Long batchId, Long completedBy, String completedByName, String remark) {
        return taskOperationService.completePublishBatchTaskForBatch(batchId, completedBy, completedByName, remark);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeScheduleTaskForSalesOrder(Long salesOrderId, Long completedBy, String completedByName, String remark) {
        return taskOperationService.completeScheduleTaskForSalesOrder(salesOrderId, completedBy, completedByName, remark);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeScheduleTaskForRdoOrder(Long rdoOrderId, Long completedBy, String completedByName, String remark) {
        return taskOperationService.completeScheduleTaskForRdoOrder(rdoOrderId, completedBy, completedByName, remark);
    }
    // ==================== 批量操作相关 ===================

    // ==================== 权限检查相关 ====================

    @Override
    public boolean checkCanClaim(Long taskId, User user) {
        return taskPermissionService.checkCanClaim(taskId, user);
    }

    @Override
    public boolean checkCanProcess(Long taskId, User user) {
        return taskPermissionService.checkCanProcess(taskId, user);
    }

    @Override
    public boolean checkCanViewAttachment(Long taskId, User user) {
        return taskPermissionService.checkCanViewAttachment(taskId, user);
    }

    @Override
    public boolean checkCanComplete(Long taskId, User user) {
        return taskPermissionService.checkCanComplete(taskId, user);
    }

    @Override
    public void calculateTaskPermissions(WorkflowTaskVO taskVO, User currentUser) {
        taskPermissionService.calculateTaskPermissions(taskVO, currentUser);
    }

    @Override
    public List<WorkflowTask> getMyClaimedProcessSheetTasks(Long userId) {
        LambdaQueryWrapper<WorkflowTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkflowTask::getTaskType, "CREATE_PROCESS_SHEET")
                .eq(WorkflowTask::getClaimedBy, userId)
                .eq(WorkflowTask::getTaskStatus, "IN_PROGRESS")
                .eq(WorkflowTask::getIsDelete, 0)
                .orderByDesc(WorkflowTask::getClaimedTime);

        return workflowTaskMapper.selectList(queryWrapper);
    }

}